home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / SYQUEST / SQHDX / DRIVER.S < prev    next >
Encoding:
Text File  |  2001-02-09  |  38.1 KB  |  1,648 lines

  1.     .title    'AHDI Atari Hard Disk Driver 9.00'
  2.  
  3. ;------------------------------------------------------------------------
  4. ;                                    :
  5. ;    AHDI Hard Disk Driver for the Atari ST                :
  6. ;    Copyright 1985,1986,1987 Atari Corp.                :
  7. ;    All Rights Reserved                        :
  8. ;                                    :
  9. ;------------------------------------------------------------------------
  10.  
  11.  
  12. ;----------------
  13. ;
  14. ;  Conditional Assembly Switches
  15. ;
  16. sermsg        equ    0        ; for timeout messages
  17. sahdxc        equ    0        ; simple atari hard disk command
  18. format        equ    1        ; include format code
  19. ospool        equ    1        ; increase size of OS pool for ROM
  20.  
  21.  
  22. ;---
  23. ;   Default drive size,
  24. ;   exactly one of the following:
  25. ;
  26. s20mb        equ    1        ; 20 Mb drive
  27. s10mb        equ    0        ; 10 Mb drive
  28.  
  29.  
  30.     .subttl    'Edit History'
  31.  
  32. ;------------------------------------------------------------------------
  33. ;                                    :
  34. ; 23-Jan-1987 lmd    Converted to MADMAC, added configurable pool    :
  35. ;    version 9.00    setup, cleaned up several years of source-code    :
  36. ;            abuse.  Fixed the date-probe problem in the OS    :
  37. ;            version-check code.                :
  38. ;                                    :
  39. ;---------------- Ancient History:                    :
  40. ;                                    :
  41. ;  9-Apr-1985 lmd    Hacked it up.  "Gee, it seems to work ..."    :
  42. ; 14-Apr-1985 lmd    linked with BIOS (***FOR NOW***)        :
  43. ; 20-Apr-1985 lmd    hacked for WD controller (now, wired...)    :
  44. ; 24-Jun-1985 jwt    hacked for Adaptec, new kludge board        :
  45. ; 01-Jul-1985 jwt    seems to work, add more formatting and more    :
  46. ;             detailed error reporting            :
  47. ; 22-Jul-1985 jwt    change timing of wdc/wdl at start of command,    :
  48. ;             added extra move.w $8a,wdl to change A1    :
  49. ; 23-Jul-1985 jwt    use a move.l instruction for all wdc/wdl write    :
  50. ;             pairs since it changes A1 quickly enough that    :
  51. ;             the (old) DMA chip does not incorrectly    :
  52. ;             generate two chip selects            :
  53. ; 26-Sep-1985 jwt v0.05    support multiple ACSI devices            :
  54. ;            separate timeouts for command packet and    :
  55. ;             operation                    :
  56. ; 01-Oct-1985 jwt v0.06    added some AUXout serial debug messages        :
  57. ;            was responding to one more drive than was there    :
  58. ; 07-Oct-1985 jwt v0.07    added support for multiple partitions/drive    :
  59. ; 11-Oct-1985 jwt v0.08 added delay loop after pread for completion    :
  60. ;             byte                        :
  61. ; 19-Oct-1985 jwt v0.09    remove format and simple commands from resident :
  62. ;             part                        :
  63. ;            conditional assembly for default size        :
  64. ;            added count parameter to pread            :
  65. ; 22-Oct-1985 jwt v0.10    make certain qdone returns d0=-1 on timeout    :
  66. ;            add bits to read/write flag for:        :
  67. ;             retry disable (bit 2)                :
  68. ;             physical unit operation (bit 3)        :
  69. ;            add pun_ptr to TOS global variables        :
  70. ; 24-Oct-1985 jwt v0.11    add critical error call on errors        :
  71. ; 30-Jan-1986 lmd v0.12    increase OS pool by 128 chunks for ROM release    :
  72. ;             of 11/20/85                    :
  73. ;          jwt    stay resident if any physical units found    :
  74. ;             rather than if any GEM partitions found    :
  75. ; 05-Feb-1986 jwt    call critical error handler on errors unless    :
  76. ;             no-retry bit is set                :
  77. ;            conditional assembly format code        :
  78. ;            remove transfer only to even byte boundary    :
  79. ;             restriction                    :
  80. ;            remove transfer less than 128K restriction    :
  81. ;            check for 0 length transfer            :
  82. ; 06-Feb-1986 jwt v0.13    use register based accesses for wdc and wdl    :
  83. ; 25-Mar-1986 lmd v0.14 Enforce .0005 (200th) sec delay between        :
  84. ;            successive calls to _do_rw().  SCSI adapter    :
  85. ;            board eat's the controller's completion byte,    :
  86. ;            so we have to delay for it.            :
  87. ; 24-Apr-1986 lmd v1.1    Hack pool_install code to increase pool for    :
  88. ;            other ROM releases of the system.        :
  89. ; 24-Apr-1986 lmd v1.4    Print nasty messages for old disk-based and    :
  90. ;            unauthorized ROM-based systems.            :
  91. ;                                    :
  92. ;------------------------------------------------------------------------
  93.  
  94.     .subttl    'Equates and Declarations'
  95.  
  96. etv_critic    equ    $404        ; critical error handoff vector
  97. flock        equ    $43e        ; FIFO lock variable
  98. _bootdev    equ    $446        ; default boot device
  99. _hz_200        equ    $4ba        ; system 200hz timer
  100. hdv_init    equ    $46a        ; hdv_init()
  101. hdv_bpb        equ    $472        ; hdv_bpb(dev)
  102. hdv_rw        equ    $476        ; hdv_rw(rw, buf, count, recno, dev)
  103. hdv_boot    equ    $47a        ; hdv_boot()
  104. hdv_mediach    equ    $47e        ; hdv_mediach(dev)
  105. _drvbits    equ    $4c2        ; block device bitVector
  106. _dskbufp    equ    $4c6        ; pointer to common disk buffer
  107. pun_ptr        equ    $516        ; pointer to physical unit table
  108.  
  109. maxunits    equ    16        ; maximum number of units
  110. nretries    equ    3        ; #retries-1
  111.  
  112. MAXSECTORS    equ    254        ; maximum number of sectors at one gulp
  113.  
  114. EWRITF        equ    -10        ; GEMDOS error codes
  115. EREADF        equ    -11
  116. CRITRETRY    equ    $00010000    ; "retry" return code
  117.  
  118. _sysbase    = $4f2            ; -> base of OS
  119. chunksiz    = 66            ; #bytes/chunk
  120. chunkno        = 4            ; chunk# (4 16-byte chunks)
  121.  
  122.     .subttl    'Entry Points'
  123.  
  124. ;----------------
  125. ;
  126. ;  Entry points:
  127. ;
  128. ;    +0   GEMDOS entry point (double-click, or \AUTO folder on floppy)
  129. ;    +4   Boot entry point (from driver file off of C:)
  130. ;    +8   Reserved for future use
  131. ;    +$C  $F0AD magic number
  132. ;    +$E  # chunks to add to pool
  133. ;
  134. i_sasi:    bra.w    i_sasi1            ; GEMDOS entry-point
  135.     bra.w    iboot            ; Boot entry-point
  136.     bra.w    iboot            ; (unused, reserved)
  137.  
  138.  
  139. ;----------------
  140. ;
  141. ;  Patchable (?) variables
  142. ;
  143. YAMagicNumber:    dc.w    $f0ad        ; wasn't here in previous releases
  144. Version:    dc.w    $0900        ; version number
  145. numchunks:    dc.w    128        ; #chunks in pool
  146. bootloaded:    dc.w    0        ; nonzero if loaded from boot sector
  147. baseaddr:    dc.l    0        ; -> base addr of .PRG file
  148.  
  149.  
  150.  
  151. ;----------------
  152. ;
  153. ;  Boot entry;
  154. ;    set "bootloaded", record base address from boot loader,
  155. ;    and continue with normal boot process.
  156. ;
  157. iboot:    st    bootloaded        ; boot entry-point, set flag
  158.     move.l    a2,baseaddr        ; install base address
  159.     bra    i_sasi1            ; (continue with normal initialization)
  160.  
  161.     .subttl    'Front End'
  162.  
  163. ;----------------
  164. ;
  165. ;  Return pointer to BPB (or NULL)
  166. ;
  167. ;    Synopsis:    LONG hbpb(dev)
  168. ;            WORD dev;
  169. ;
  170. hbpb:    .cargs .dev.w
  171.     move.w    .dev(sp),d0        ; d0 = devno
  172.     clr    d1            ; d1 = 0, physical op not possible
  173.     move.l    o_bpb,a0        ; a0 -> pass-through vector
  174.     lea    _sasi_bpb(pc),a1    ; a1 -> our handler
  175.     bra    check_dev        ; do it
  176.  
  177.  
  178.  
  179. ;----------------
  180. ;
  181. ;  Read or write logical sectors
  182. ;
  183. ;    Synopsis:    LONG rw(rw, buf, count, recno, dev)
  184. ;            WORD rw;
  185. ;            char *buf;
  186. ;            WORD count;
  187. ;            WORD recno;
  188. ;            WORD dev;
  189. ;
  190. hrw:    .cargs    .rw.w, .buf.l, .count.w, .recno.w, .dev.w
  191.     move.w    .dev(sp),d0        ; d0 = devno
  192.     move.w    .rw(sp),d1        ; d1 includes physical device flag
  193.     move.l    o_rw,a0            ; a0 -> pass-through vector
  194.     lea    _sasi_rw(pc),a1        ; a1 -> our handler
  195.     bra    check_dev        ; do it
  196.  
  197.  
  198.  
  199. ;----------------
  200. ;
  201. ;  Check for media change
  202. ;
  203. ;    Synopsis:    LONG mediach(dev)
  204. ;            WORD dev;
  205. ;
  206. hmediach: .cargs .dev.w
  207.     move.w    .dev(sp),d0        ; d0 = devno
  208.     clr    d1            ; physical operation not possible
  209.     move.l    o_mediach,a0        ; a0 -> pass-through vector
  210.     lea    _sasi_mediach(pc),a1    ; a1 -> our handler
  211.  
  212.  
  213. ;----------------
  214. ;
  215. ;  check_dev - use handler, or pass vector through
  216. ;
  217. ;  Passed:    d0.w = device#
  218. ;        d1, bit 3  1=physical operation
  219. ;        a0 ->  old handler
  220. ;        a1 ->  new handler
  221. ;        a5 ->  $0000 (zero-page ptr)
  222. ;
  223. ;  Jumps-to:    (a1) if dev in range for this handler
  224. ;        (a0) otherwise
  225. ;
  226. check_dev:
  227.     btst    #3,d1            ; is this a physical unit operation?
  228.     beq.s    .phys            ; (yes, use raw number)
  229.  
  230.     subq    #2,d0            ; lowest device is C:
  231.     bmi.s    .fail            ; not one of ours
  232.  
  233.     cmp    puns,d0
  234.     bge.s    .fail
  235.     bra.s    .succ
  236.  
  237. .phys:    lea    pun,a2            ; pointer to pun map
  238.     tst.b    (a2,d0.w)        ; must be positive for a real unit
  239.     bmi.s    .fail
  240. .succ:    move.l    a1,a0            ; yes -- follow success vector
  241. .fail:    jmp    (a0)            ; do it
  242.  
  243.  
  244.  
  245.     .subttl    'Medium Level Driver'
  246.  
  247. ;----------------
  248. ;
  249. ;  Initialize SASI device
  250. ;
  251. ;    Passed:    nothing
  252. ;    Returns:    d0 < 0: error
  253. ;        d0 ==0: success
  254. ;
  255. _sasi_init:
  256.     clr.l    d0
  257.     rts
  258.  
  259.  
  260. ;----------------
  261. ;
  262. ;  Return BPB for logical device
  263. ;
  264. ;    Synopsis:    LONG _sasi_bpb(dev)
  265. ;            WORD dev;
  266. ;
  267. ;    Returns:    NULL, or a pointer to the BPB buffer
  268. ;
  269. ;-
  270. _sasi_bpb: .cargs .dev.w
  271.     move.w    .dev(sp),d0        ; get device number
  272.     mulu.w    #BPBLEN,d0
  273.     add.l    #bpbs,d0
  274.     rts
  275.  
  276.     .eject
  277.  
  278. ;----------------
  279. ;
  280. ;  Read/Write sectors
  281. ;
  282. ;    Synopsis:    _ahdi_rw(rw, buf, count, recno, dev)
  283. ;            WORD rw;
  284. ;            char *buf;
  285. ;            WORD count;
  286. ;            WORD recno;
  287. ;            WORD dev;
  288. ;
  289. ; Passed:    dev    $e(sp).W
  290. ;        recno    $c(sp).W
  291. ;        count    $a(sp).W
  292. ;        buf    6(sp).L
  293. ;        rw    4(sp).W        ; non-zero -> write
  294. ;
  295. _sasi_rw:
  296. _ahdi_rw: .cargs #8, .rw, .buf.l, .count, .recno, .dev
  297.     link    a6,#0            ; create a frame pointer
  298.  
  299. .1:    move.w    .count(a6),d2        ; is there anything to be done?
  300.     beq    .6            ; no, so done with no errors
  301.  
  302.     move.l    .buf(a6),d1        ; if all goes well, this is our buffer
  303.  
  304.     cmpi.w    #MAXSECTORS,d2        ; more than one DMAfull?
  305.     ble    .2
  306.     move.w    #MAXSECTORS,d2        ; yes, so only do this many this time
  307.  
  308. .2:    btst    #0,.buf+3(a6)        ; an odd boundary?
  309.     beq    .4            ; no, so do normally
  310.  
  311.     cmpi.w    #2,d2            ; can only do 2 at a time tops this way
  312.     ble    .3
  313.     move.w    #2,d2
  314.  
  315. .3:    move.l    _dskbufp,d1        ; use the bios buffer for this transfer
  316.  
  317.     btst    #0,.rw+1(a6)        ; is this a write?
  318.     beq    .4            ; no, so go fill buffer from disk
  319.  
  320.     movea.l    d1,a1            ; dest
  321.     movea.l    .buf(a6),a2        ; source
  322.     bsr    smove            ; move d2 sectors from a2 to a1
  323.  
  324. .4:    move.w    d2,-(sp)        ; preserve count this time
  325.  
  326.     move.w    .dev(a6),-(sp)
  327.     move.w    .recno(a6),-(sp)
  328.     move.w    d2,-(sp)        ; count
  329.     move.l    d1,-(sp)        ; buffer
  330.     move.w    .rw(a6),-(sp)
  331.     bsr    _do_rw
  332.     adda.w    #12,sp
  333.  
  334.     move.w    (sp)+,d2        ; restore count for this op
  335.  
  336.     tst.l    d0            ; any errors there?
  337.     bne    .7            ; yes, so give up
  338.  
  339.     btst    #0,.buf+3(a6)        ; if odd boundary
  340.     beq    .5
  341.     btst    #0,.rw+1(a6)        ; and a read
  342.     bne    .5
  343.  
  344.     movea.l    .buf(a6),a1        ; we must move dskbuf to desired dest
  345.     movea.l    _dskbufp,a2
  346.     bsr    smove
  347.  
  348. .5:    move.w    d2,d0            ; number we did
  349.     ext.l    d0
  350.     asl.l    #8,d0            ; *512
  351.     asl.l    #1,d0
  352.     add.l    d0,.buf(a6)        ; buf += (sectors_done * sector size)
  353.     add.w    d2,.recno(a6)
  354.     sub.w    d2,.count(a6)
  355.     bne    .1
  356.  
  357. .6:    clr.l    d0            ; got here with no errors!
  358. .7:    unlk    a6
  359.     rts
  360.  
  361. ;----------------
  362. ;
  363. ;  Copy unaligned sectors
  364. ;  (this is *supposed* to be slow!)
  365. ;
  366. ;    Passed:    d2.w    = # of sectors (known to be 1 or 2)
  367. ;        a2    -> source sector
  368. ;        a1    -> dest buffer (oddly aligned)
  369. ;
  370. smove:    move.w    d2,d0            ; d0 = (d2 * 512) - 1
  371.     asl.w    #8,d0
  372.     asl.w    #1,d0
  373.     subq.w    #1,d0
  374. .1:    move.b    (a2)+,(a1)+
  375.     dbra    d0,.1
  376.     rts
  377.  
  378.     .eject
  379. ;+
  380. ; _do_rw - called to read/write no more than 128K to an even boundary
  381. ;
  382. ; Passed:    dev    $e(sp).W
  383. ;        recno    $c(sp).W
  384. ;        count    $a(sp).W
  385. ;        buf    6(sp).L
  386. ;        rw    4(sp).W        ; non-zero -> write
  387. ;
  388. ;-
  389. _do_rw:
  390.     move.w    d3,-(sp)        ; preserve d3
  391.  
  392. .0:    move.w    _retries,retrycnt    ; setup retry counter
  393.  
  394.     move.w    6(sp),d3
  395.     btst    #2,d3            ; are retries disabled?
  396.     beq    .1            ; no, act normally
  397.     move.w    #0,retrycnt        ; yes, so set retrycnt to zero
  398.  
  399. ;
  400. ; read sector(s),
  401. ; delay .0005 to .001 seconds between driver calls
  402. ;
  403. .1:
  404.     move.l    lastrwtm,d0
  405. .8:    cmp.l    _hz_200,d0        ; while (_hz_200 <= lastrwtm)
  406.     bcc    .8            ;    just_wait;
  407.     move.l    _hz_200,d0        ; lastrwtm = _hz_200 + 1;
  408.     addq.l    #1,d0
  409.     move.l    d0,lastrwtm
  410.  
  411.     lea    2(sp),a1        ; frame pointer
  412.     moveq    #0,d0            ; coerce word to long, unsigned
  413.     move.w    $c(a1),d0        ; sect.L
  414.     move.w    4(a1),d3        ; rw
  415.  
  416.     btst    #3,d3            ; physical unit operation
  417.     beq    .2            ; no, so do log->phys mapping
  418.  
  419.     move    $0e(a1),d2        ; get unit number
  420.     subq    #2,d2            ; subtract drive C offset
  421.     bra    .3            ; and use that as the physical unit
  422.  
  423. .2:    clr    d2            ; coerce byte to word
  424.     move.w    $e(a1),d1        ; get device
  425.     lea    pun,a2
  426.     move.b    0(a2,d1.w),d2        ; get physical unit number
  427. .3:    move.w    d2,-(sp)        ; dev
  428.     move.l    6(a1),-(sp)        ; buf
  429.     move.w    $a(a1),-(sp)        ; count
  430.  
  431.     btst    #3,d3            ; physical operation?
  432.     bne    .4            ; yes, so no offset
  433.  
  434.     asl.w    #2,d1            ; *4 to get index into long array
  435.     lea    start,a2
  436.     add.l    0(a2,d1.w),d0        ; adjust sector number
  437.  
  438. .4:    move.l    d0,-(sp)        ; sect
  439.     btst    #0,d3            ; read or write?
  440.     bne    .5            ; (write)
  441.     bsr    _hread            ; read sectors
  442.     bra    .6
  443. .5:    bsr    _hwrite            ; write sectors
  444. .6:    add.w    #12,sp            ; (cleanup stack)
  445.     tst.l    d0            ; errors?
  446.     beq    .r            ; no -- success
  447.     subq.w    #1,retrycnt        ; drop retry count and retry
  448.     bpl    .1
  449.  
  450.     move    6(sp),d1        ; get r/w and flags word
  451.     move.l    #EREADF,d0        ; read error code
  452.     btst    #0,d1
  453.     beq    .7
  454.     move.l    #EWRITF,d0        ; write error code
  455.  
  456. .7:    btst    #2,d1            ; is this a "raw" operation?
  457.     bne    .r            ; yes, so no critical error handler
  458.  
  459.     move.w    $10(sp),-(sp)        ; unit number
  460.     move.w    d0,-(sp)        ; error code (as a word, sic)
  461.     movea.l    etv_critic,a0
  462.     jsr    (a0)
  463.     addq    #4,sp
  464.     cmpi.l    #CRITRETRY,d0        ; is it the magic RETRY code?
  465.     beq    .0
  466.  
  467. .r:    move.w    (sp)+,d3        ; remember to restore d3
  468.     rts
  469.  
  470.  
  471. ;----------------
  472. ;
  473. ;  Check for media change on hard disk
  474. ;   (this never happens)
  475. ;
  476. ;    synopsis:    _sasi_mediach(dev)
  477. ;            WORD dev;
  478. ;
  479. ;    Returns:    0L (always)
  480. ;
  481. ;-
  482. _sasi_mediach:
  483.     clr.l    d0
  484.     rts
  485.  
  486.  
  487.     .subttl    'Low-Level Driver'
  488.  
  489. ;----------------
  490. ;
  491. ;  Hardware definitions
  492. ;
  493. wdc        equ    $ffff8604
  494. wdl        equ    $ffff8606
  495. wdcwdl        equ    wdc        ; used for long writes
  496. xwdl        equ    wdl-wdc        ; offset from wdc to wdl
  497.  
  498. dmahi        equ    $ffff8609
  499. dmamid        equ    dmahi+2
  500. dmalow        equ    dmamid+2
  501. gpip        equ    $fffffa01
  502.  
  503.  
  504. ;----------------
  505. ;
  506. ;  Tunable (delay) values
  507. ;
  508. ltimeout        equ    450000        ; long-timeout (3 S)
  509. stimeout        equ    15000        ; short-timeout (100 mS)
  510.  
  511.  
  512. ;----------------
  513. ;
  514. ;  LONG _qdone() - Wait for command byte handshake
  515. ;  LONG _fdone() - Wait for operation complete
  516. ;
  517. ;  Passed:    nothing
  518. ;
  519. ;  Returns:    EQ: no timeout
  520. ;        MI: timeout condition
  521. ;
  522. ;  Uses:        D0
  523. ;
  524. ;    Each pass through the loop takes 6.75 uS
  525. ;
  526. _fdone:    move.l    #ltimeout,tocount    ; setup for long timeout
  527.     bra.s    qd1
  528.  
  529. _qdone:    move.l    #stimeout,tocount    ; setup for short timeout
  530. qd1:    subq.l    #1,tocount        ; drop timeout count
  531.     bmi.s    .quit            ; (I give up, return NE)
  532.     btst    #5,gpip            ; interrupt?
  533.     bne.s    qd1            ; (not yet)
  534.     moveq    #0,d0            ; return EQ (no timeout)
  535.     rts
  536. .quit:    moveq    #-1,d0            ; return NE (timeout)
  537.     rts
  538.  
  539.  
  540. ;----------------
  541. ;
  542. ;  Wait for end of SASI command
  543. ;
  544. ;  Passed:    d0 value to be written to wdl
  545. ;
  546. ;  Returns:    EQ: success (error code in D0.W)
  547. ;        MI: timeout
  548. ;        NE: failure (SASI error code in D0.W)
  549. ;
  550. ;  Uses:    d0,d1
  551. ;
  552. _endcmd:
  553.     move    d0,d1            ; preserve wdl value
  554.     bsr    _fdone            ; wait for operation complete
  555.     bmi.s    .end            ; (timed-out, so complain)
  556.     move.w    d1,wdl            ; write controller register
  557.     NOP                ; [magic delay]
  558.     move.w    wdc,d0            ; get the result
  559.     and.w    #$00ff,d0        ; (clean it up), if non-zero should
  560. .end:    rts                ;  do a ReadSense command to learn more
  561.  
  562.  
  563. ;----------------
  564. ;
  565. ;  _hread(sectno, count, buf, dev)
  566. ;    LONG sectno;     4(sp)
  567. ;    WORD count;     8(sp)
  568. ;    LONG buf;        $a(sp)    $b=high, $c=mid, $d=low
  569. ;    WORD dev;        $e(sp)
  570. ;
  571. ; Returns:    -1 on timeout
  572. ;        0 on success
  573. ;        nonzero on error
  574. ;
  575. ;-
  576. _hread:    .cargs .sectno.l .count.w .buf.l .dev.w
  577.     lea    wdc.w,a0        ; a0 -> DMA chip
  578.     st    flock            ; lock FIFO
  579.  
  580.     move    #$88,xwdl(a0)
  581.     clr.l    d0
  582.     move.w    .dev(sp),d0        ; get unit number
  583.     lsl.w    #5,d0
  584.     swap    d0
  585.     ori.l    #$0008008a,d0        ; 08 wdc, 8a wdl
  586.     move.l    d0,(a0)            ; wdcwdl [long write]
  587.  
  588.     move.l    .buf(sp),-(sp)        ; set DMA address
  589.     bsr    _setdma
  590.     addq    #4,sp
  591.  
  592.     bsr    _setss            ; set sector and size
  593.     bmi    _hto            ; (punt on failure)
  594.  
  595.     move.w    #$190,xwdl(a0)        ; toggle R/W to reset chip
  596.     NOP                ; magic delay
  597.     move.w    #$90,xwdl(a0)        ; select sector count register
  598.     NOP                ; magic delay
  599.     move.w    8(sp),(a0) ;wdc        ; write sector count to DMA chip
  600.     NOP                ; magic delay
  601.     move.w    #$8a,xwdl(a0)        ; ??? select bus again ???
  602.     NOP                ; magic delay
  603.     move.l    #$00000000,(a0)        ; write control byte, 0 wdc 0 wdl
  604.  
  605.     move.w    #$8a,d0            ; ???
  606.     bsr    _endcmd
  607.     bra    _hdone            ; cleanup after IRQ
  608.  
  609.  
  610. ;----------------
  611. ;
  612. ;  _hwrite(sectno, count, buf, dev)
  613. ;    LONG sectno;     4(sp)
  614. ;    WORD count;     8(sp)
  615. ;    LONG buf;        $a(sp)    $b=high, $c=mid, $d=low
  616. ;    WORD dev;        $e(sp)
  617. ;
  618. ;-
  619. _hwrite: .cargs .sectno.l .count.w .buf.l .dev.w
  620.     lea    wdc.w,a0        ; a0 -> DMA chip
  621.     st    flock            ; set lock variable
  622.  
  623.     move.l    .buf(sp),-(sp)        ; set DMA address
  624.     bsr    _setdma
  625.     addq    #4,sp
  626.  
  627.     move.w    #$88,xwdl(a0)
  628.     clr.l    d0
  629.     move.w    .dev(sp),d0        ; get unit number
  630.     lsl.w    #5,d0
  631.     swap    d0
  632.     ori.l    #$000a008a,d0        ; 0a wdc 8a wdl
  633.     move.l    d0,(a0)            ; wdcwdl
  634.  
  635.     bsr    _setss
  636.     bmi    _hto
  637.  
  638.     move.w    #$90,xwdl(a0)        ; toggle R/W to reset chip
  639.     NOP
  640.     move.w    #$190,xwdl(a0)        ; select sector count register
  641.     NOP
  642.     move.w    8(sp),(a0) ;wdc        ; sector count for DMA chip's benefit
  643.     NOP
  644.     move.w    #$18a,xwdl(a0)        ; ???
  645.     NOP
  646.     move.l    #$00000100,(a0)        ; wdcwdl
  647.  
  648.     move.w    #$18a,d0
  649.     bsr    _endcmd
  650.     bra    _hdone            ; cleanup after IRQ
  651.  
  652.  
  653. ;----------------
  654. ;
  655. ;  Set DMA address
  656. ;
  657. ;    _setdma(addr)
  658. ;    LONG addr;
  659. ;
  660. _setdma:
  661.     move.b    7(sp),dmalow
  662.     move.b    6(sp),dmamid
  663.     move.b    5(sp),dmahi
  664.     rts
  665.  
  666.  
  667. ;----------------
  668. ;
  669. ;  Set sector number and number of sectors
  670. ;
  671. _setss:    move.w    #$8a,xwdl(a0)
  672.  
  673.     bsr    _qdone            ; wait for controller to take command
  674.     bmi    setsse
  675.  
  676.     move.b    9(sp),d0        ; construct sector#
  677.     swap    d0
  678.     move.w    #$008a,d0
  679.     move.l    d0,(a0) ; wdcwdl    ; write MSB sector# + devno
  680.     bsr    _qdone
  681.     bmi    setsse
  682.  
  683.     move.b    10(sp),d0        ; write MidSB sector#
  684.     swap    d0
  685.     move.w    #$008a,d0
  686.     move.l    d0,(a0) ; wdcwdl
  687.     bsr    _qdone
  688.     bmi    setsse
  689.  
  690.     move.b    11(sp),d0        ; write LSB sector#
  691.     swap    d0
  692.     move.w    #$008a,d0
  693.     move.l    d0,(a0) ; wdcwdl
  694.     bsr    _qdone
  695.     bmi    setsse
  696.  
  697.     move.w    12(sp),d0        ; write sector count
  698.     swap    d0
  699.     move.w    #$008a,d0
  700.     move.l    d0,(a0) ; wdcwdl
  701.     bsr    _qdone
  702.  
  703. setsse:    rts
  704.  
  705.  
  706. ;----------------
  707. ;
  708. ;  Handle command timeout;
  709. ;  Unlock DMA chip and return completion status;
  710. ;
  711. _hto:    moveq    #-1,d0        ; indicate timeout
  712. _hdone:    move.w    #$80,wdl    ; Landon's code seems to presume we
  713.     nop            ;  put this back to $80
  714.     tst.w    wdc
  715.     clr    flock        ; NOW, signal that we are done
  716.     rts
  717.  
  718.     .subttl    'Resident Installer'
  719. ;----------------
  720. ;
  721. ;
  722. isasi5:    bsr    pool_install    ; attempt to install more OS pool
  723.     move.l    d0,-(sp)    ; preserve the number of bytes we need
  724.  
  725.     tst.w    bootloaded    ; if bootloaded, then already in super mode
  726.     bne    nboot1        ; (already there)
  727.     move.l    savssp,-(sp)    ; become a mild mannered user process
  728.     move.w    #$20,-(sp)    ; Super(savssp)
  729.     trap    #1
  730.     addq    #6,sp
  731.  
  732. nboot1:    move.l    (sp)+,d0    ; compute value for Ptermres() or Mshrink
  733.     add.l    #((i_sasi1-i_sasi)+$0100),d0
  734.  
  735.     tst.w    bootloaded    ; exit to GEMDOS?
  736.     beq    nboot2        ; (yes -- not boot loaded)
  737.  
  738. ;----------------
  739. ;
  740. ;  Return to TOS ROMs
  741. ;    o  set default boot device to C:
  742. ;    o  Print silly message
  743. ;    o  Mshrink() memory that was alloc'd to us
  744. ;    o  set magic# in D7 for TOS ROMs
  745. ;    o  RTS back to ROMs
  746. ;
  747.     move.l    d0,-(sp)        ; save D0
  748.     pea    msg_loaded(pc)        ; print announcement
  749.     move.w    #9,-(sp)
  750.     trap    #1
  751.     addq    #6,sp
  752.     move.l    (sp)+,d0
  753.  
  754.     move.w    #2,_bootdev        ; set default boot device to C:
  755.     move.l    d0,-(sp)
  756.     move.l    baseaddr,-(sp)
  757.     clr.w    -(sp)
  758.     move.w    #$4a,-(sp)        ; Mshrink(...)
  759.     trap    #1
  760.     add.w    #12,sp            ; (cleanup stack)
  761.  
  762.  
  763. exec_os        equ    $4fe
  764.  
  765. ;----------------
  766. ;
  767. ;  Bring up the AES:
  768. ;    do autoexec;
  769. ;    construct an enviroment string;
  770. ;    create a basepage for the AES;
  771. ;    exec the AES.
  772. ;
  773. st_1:
  774.     bsr    _auto            ; do auto-exec
  775.     pea    orig_env        ; push address of enviroment string
  776.     pea    nullenv(pc)        ; no arguments
  777.     pea    nullenv(pc)        ; null shell name (in ROM, after all)
  778.     move.w    #5,-(sp)        ; createPSP flavor of exec
  779.     move.w    #$4b,-(sp)        ; exec function#
  780.     trap    #1            ; get pointer to PSP
  781.     add.w    #14,sp            ; (clean up cruft)
  782.     move.l    d0,a0            ; a0 -> PSP
  783.     move.l    exec_os,8(a0)        ; stuff saddr of GEM in PSP
  784.  
  785.     move.l    a0,-(sp)        ; push addr of PSP
  786.     pea    nullenv(pc)        ; null filename
  787.     move.w    #4,-(sp)        ; just-go
  788.  
  789. st_x:    move.w    #$4b,-(sp)        ; function = exec
  790.     trap    #1            ; do it
  791.     add.w    #14,sp            ; cleanup stack
  792.  
  793. ;---
  794. ;   When startup fails (or if the exec returns,
  795. ;   which "cannot happen") then fake a system reset:
  796. ;
  797.     move.l    4,a0            ; get RESET vector
  798.     jmp    (a0)            ; ... then fake a RESET
  799.  
  800.  
  801.  
  802. ;---
  803. ;   Default enviroment string
  804. ;
  805. orig_env:
  806.     dc.b    "PATH=",0        ; default pathname
  807.     dc.b    "C:\\",0        ; is the boot device
  808.     dc.b    0            ; terminate env string
  809.  
  810.  
  811. gemname: dc.b    "GEM.PRG"        ; desktop name
  812. nullenv: dc.b    0,0            ; null string (and enviroment)
  813.     even
  814.  
  815.  
  816. ;---
  817. ;   Auto path for hard disks (C:)
  818. ;
  819. autopath:    dc.b    'C:\\AUTO\\'
  820. autofile:    dc.b    '*.PRG',0
  821.         dc.w    $1234,$5678,$9abc,$def0
  822.     even
  823.  
  824.     .subttl    '\\AUTO Folder Execution'
  825. ;----------------
  826. ;
  827. ;  _auto    exec auto-startup files in the appropriate subdirectory
  828. ;  _auto1    exec (with filename args)
  829. ;
  830. ;    Passed:    a0 -> full filespec (pathname)
  831. ;        a1 -> filename part of filespec
  832. ;
  833. ;    Returns:    nothing
  834. ;
  835. ;    Uses:    everything
  836. ;
  837. _auto:    lea    autopath(pc),a0        ; -> path
  838.     lea    autofile(pc),a1        ; -> filename
  839.  
  840. _auto1:    move.l    (sp)+,autoret        ; copy return addr (used by execlr)
  841.     move.l    sp,origstk        ; (save original stack)
  842.     move.l    a0,pathname        ; setup filename/pathname ptrs
  843.     move.l    a1,filename
  844.  
  845.     lea    nullenv(pc),a3        ; a0 -> \0\0
  846.     move.l    a3,-(sp)        ; null enviroment
  847.     move.l    a3,-(sp)        ; null command tail
  848.     move.l    a3,-(sp)        ; null shell name
  849.     move.w    #5,-(sp)        ; Create-PSP subfunction
  850.     move.w    #$4b,-(sp)        ; exec function#
  851.     trap    #1            ; do DOS call
  852.     add.w    #16,sp
  853.  
  854.     move.l    d0,a0            ; a0 -> PSP
  855.     move.l    #fauto,8(a0)        ; initial PC -> autoexec prog
  856.  
  857.     move.l    a3,-(sp)        ; null enviroment
  858.     move.l    d0,-(sp)        ; -> PSP
  859.     move.l    a3,-(sp)        ; null shell name
  860.     move.w    #4,-(sp)        ; just-go
  861.     move.w    #$4b,-(sp)        ; function = exec
  862.     trap    #1            ; do it
  863.     add.w    #16,sp            ; cleanup stack & goodbye
  864. autoq:    move.l    autoret,-(sp)
  865.     rts
  866.  
  867.  
  868.  
  869. ;----------------
  870. ;
  871. ;  fauto    Pexec()'d by _auto to do autostartup
  872. ;
  873. ;    Passed:    pathname -> path part of filespec
  874. ;        filename -> file part of filespec
  875. ;
  876. fauto:
  877.     move.w    #2,-(sp)        ; Dsetdrv(2)
  878.     move.w    #$e,-(sp)
  879.     trap    #1
  880.     addq    #4,sp
  881.  
  882.     clr.l    -(sp)            ; get into super mode
  883.     move.w    #$20,-(sp)
  884.     trap    #1
  885.     addq    #6,sp            ; cleanup
  886.     move.l    d0,a4            ; a4 -> saved super stack
  887.  
  888. ;---
  889. ;   free up some memory:
  890. ;
  891.     move.l    4(a7),a5        ; a5 -> base page
  892.     lea    $100(a5),sp        ; sp -> new, safer addr
  893.     move.l    #$100,-(sp)        ; keep $100 (just the basepage)
  894.     move.l    a5,-(sp)        ; -> start of mem to keep
  895.     clr.w    -(sp)            ; junk word
  896.     move.w    #$4a,-(sp)        ; setblock(...)
  897.     trap    #1
  898.     addq    #6,sp
  899.     tst.w    d0
  900.     bne    au_dn            ; punt on error
  901.  
  902.     move.w    #$0007,-(sp)        ; find r/o+hidden+system files
  903.     move.l    pathname,-(sp)        ; -> filename (on input)
  904.     move.w    #$4e,-(sp)        ; searchFirst
  905.  
  906.     moveq    #8,d7            ; d7 = cleanup amount
  907. au1:    pea    autodma            ; setup DTA (for search)
  908.     move.w    #$1a,-(sp)
  909.     trap    #1
  910.     addq    #6,sp
  911.  
  912.     trap    #1            ; search first/search next
  913.     add.w    d7,sp            ; cleanup stack
  914.     tst.w    d0            ; test for match
  915.     bne    au_dn            ; (no match -- quit)
  916.  
  917. ;--- construct filename from path and the name we just found:
  918.     move.l    pathname,a0        ; copy pathname
  919.     move.l    filename,a2        ; a2 -> end+1 of pathname
  920.     lea    autoname,a1
  921. au3:    move.b    (a0)+,(a1)+        ; copy path part of name
  922.     cmp.l    a0,a2            ; finished?
  923.     bne    au3            ; (no)
  924.     lea    autodma+30,a0        ; copy fname to end of pathname
  925. au2:    move.b    (a0)+,(a1)+
  926.     bne    au2
  927.  
  928.     pea    nullenv(pc)        ; null enviroment
  929.     pea    nullenv(pc)        ; no command tail
  930.     pea    autoname        ; -> file to exec
  931.     clr.w    -(sp)            ; load-and-go
  932.     move.w    #$4b,-(sp)        ; exec(...)
  933.     trap    #1
  934.     add.w    #16,sp
  935.  
  936.     moveq    #2,d7            ; reset cleanup amount
  937.     move.w    #$4f,-(sp)        ; searchNext
  938.     bra    au1
  939.  
  940. ;---
  941. ;   The first GEMDOS process can never terminate.
  942. ;   This is not a good feature.
  943. ;   Kludge around it -- re-initialize the stack
  944. ;   and return to the guy who called us to begin with.
  945. ;
  946. au_dn:    move.l    origstk,sp        ; restore original stack
  947.     move.l    autoret,-(sp)        ; get return addr
  948.     rts                ; just jump there ...
  949.  
  950.  
  951. ;--- "bss" for auto-exec:
  952. autoret:    dc.l    0        ; -> _auto's caller (yeccch)
  953. pathname:    dc.l    0        ; -> filespec's pathname
  954. filename:    dc.l    0        ; -> filename part of path
  955. origstk:    dc.l    0        ; =  original supervisor stack
  956. autodma:    dcb.b    44,0        ; 44 bytes for directory search
  957. autoname:    dcb.b    32,0        ; 32 bytes for path+filename
  958.     even
  959.  
  960.  
  961. msg_loaded:
  962.     dc.b    '----------------------',13,10
  963.     dc.b    'Atari Hard Disk Driver',13,10
  964.     dc.b    '16-Jun-1986       AHDI',13,10
  965.     dc.b    '----------------------',13,10
  966.     dc.b    0
  967.     even
  968.  
  969. ;
  970. ;  Terminate and stay resident;
  971. ;  installed driver under GEMDOS.
  972. ;
  973. nboot2:    move.w    #0,-(sp)    ; exit code
  974.     move.l    d0,-(sp)
  975.     move.w    #$31,-(sp)    ; terminate and stay resident
  976.     trap    #1        ; should never come back...
  977.     illegal
  978.  
  979.  
  980.     .subttl    'OS Pool Expansion'
  981.  
  982.     .if ospool
  983. ;----------------
  984. ;
  985. ;  Wire more pool into various ROM releases.
  986. ;
  987. ;    Passed:    nothing
  988. ;    Returns:    D0 = #bytes extra used
  989. ;
  990. ;
  991. pool_install:
  992.     move.l    _sysbase,a3        ; a3 -> base of OS
  993.  
  994. ; make sure we're in ROM,
  995. ; then get address of RAM location to patch:
  996.  
  997.     cmp.l    #$800000,a3        ; better be ROM
  998.     blt    notrom
  999.     lea    pool_tab(pc),a0        ; a0 -> table to match
  1000. pi_lp:    move.l    (a0)+,d1        ; d1 = date to match
  1001.     beq    badrom            ; (forget it, end of list)
  1002.     move.l    (a0)+,a2        ; a2 -> _root address for that date
  1003.     cmp.l    $18(a3),d1        ; match dates?
  1004.     bne    pi_lp            ; (no -- try again)
  1005.  
  1006.     lea    poolbuf+2,a0        ; a0 -> base of first buffer
  1007.     move.w    numchunks,d0        ; d0 = count-1
  1008.     subq.w    #1,d0
  1009. pin_1:    lea    chunksiz(a0),a1        ; a1 -> next buffer
  1010.     move.l    a1,(a0)            ; buffer -> next one
  1011.     move.w    #chunkno,-2(a0)        ; install chunksiz
  1012.     move.l    a1,a0            ; a0 -> next buffer
  1013.     dbra    d0,pin_1        ; (do some more)
  1014.  
  1015.     sub.w    #chunksiz,a0        ; a0 -> last block
  1016.     move.l    chunkno*4(a2),(a0)    ; last block -> first in root
  1017.     move.l    #poolbuf+2,chunkno*4(a2) ; root -> first of ours
  1018.     move.w    numchunks,d0        ; d0 = numchunks * chunksiz
  1019.     mulu    #chunksiz,d0        ;    = amount of BSS we used
  1020.     rts                ; return OK
  1021.  
  1022. ;+
  1023. ;  Print warning messages
  1024. ;  about bogus versions of the
  1025. ;  operating system.  Assume that
  1026. ;  every OS past 1-May-1986 has the
  1027. ;  pool fix installed.
  1028. ;
  1029. ;-
  1030. ok_date    =    %0000110010100001    ; 1-May-1986
  1031. notrom:    lea    m_notrom(pc),a0        ; ram-based system (5/29!)
  1032.     bra.s    bdrom1
  1033. badrom:    lea    m_badrom(pc),a0        ; illegal ROM system
  1034. bdrom1:    cmp.w    #ok_date,$1e(a3)    ; if ok_date <= os_dosdate(a3) 
  1035.     bcc    bdrom2            ; then don't print anything
  1036.  
  1037.     move.l    a0,-(sp)        ; print nasty message
  1038.     move.w    #9,-(sp)
  1039.     trap    #1
  1040.     addq    #6,sp
  1041.  
  1042. ; print msg and wait for RETURN
  1043.     pea    keymsg(pc)
  1044.     move.w    #9,-(sp)
  1045.     trap    #1
  1046.     addq    #6,sp
  1047.  
  1048. bdrom3:    move.w    #2,-(sp)        ; wait for [RETURN]
  1049.     move.w    #2,-(sp)
  1050.     trap    #13
  1051.     addq    #4,sp
  1052.     cmp.w    #13,d0
  1053.     bne    bdrom3
  1054.  
  1055. bdrom2:    moveq    #0,d0            ; 0 extra bytes used
  1056.     rts
  1057.  
  1058. keymsg:    dc.b    'Hard disk driver not loaded; hit RETURN',13,10
  1059.     dc.b    'key to continue:',13,10
  1060.     dc.b    0
  1061.  
  1062. m_notrom:
  1063.     dc.b    '*** WARNING ***',13,10,7
  1064.     dc.b    'This hard disk driver may not work with',13,10,7
  1065.     dc.b    'a disk-based version of TOS; files on',13,10,7
  1066.     dc.b    'your hard disk may be damaged.',13,10,7
  1067.     dc.b    13,10,7
  1068.     dc.b    0
  1069.  
  1070. m_badrom:
  1071.     dc.b    '*** WARNING ***',13,10,7
  1072.     dc.b    'You are using an unofficial ROM release',13,10,7
  1073.     dc.b    'of the operating system.  This driver',13,10,7
  1074.     dc.b    'may not work correctly with it.  Files',13,10,7
  1075.     dc.b    'on your hard disk may be damaged.',13,10,7
  1076.     dc.b    13,10,7
  1077.     dc.b    0
  1078.     even
  1079.  
  1080.  
  1081. ;+
  1082. ;  Table of ROM release dates / _root addresses
  1083. ;  update these for new ROM releases that need the patch.
  1084. ;
  1085. ;-
  1086. pool_tab:
  1087.     dc.l    $11201985,$56fa        ; USA and UK, 20-Nov-1985
  1088.     dc.l    $02061986,$56fa        ; Germany, 6-Feb-1986
  1089.     dc.l    $04241986,$56fa        ; France, 24-Apr-1986
  1090.     dc.l    0
  1091.     .endif
  1092.  
  1093.  
  1094.     .subttl    'Driver State'
  1095. BPBLEN    equ    18
  1096. _puns:
  1097. puns:    dc.w    0
  1098.  
  1099. _pun:
  1100. pun:    dcb.b    maxunits,0
  1101. _partstart:
  1102. start:    dcb.l    maxunits,0
  1103. bpbs:    dcb.b    maxunits*18,0
  1104.  
  1105. lastrwtm:    dc.l    0        ; ``_hz_200 + 1'' at last _do_rw()
  1106. tocount:    dc.l    1        ; timeout counter
  1107. retrycnt:    dc.w    1        ; retry counter
  1108. _retries:    dc.w    nretries    ; number of retries to do
  1109.  
  1110. o_init:        dc.l    1
  1111. o_bpb:        dc.l    1
  1112. o_rw:        dc.l    1
  1113. o_mediach:    dc.l    1
  1114.  
  1115.  .if ospool
  1116. poolbuf:    dc.w    0
  1117.  .endif
  1118.  
  1119.     .subttl    'Driver Installation'
  1120.  
  1121. ;----------------
  1122. ;
  1123. ;  Driver Installation
  1124. ;
  1125. i_sasi1:
  1126.     tst.w    bootloaded        ; if boot-loaded, don't Super()
  1127.     bne    nboot3
  1128.     clr.l    -(sp)            ; it's a bird...
  1129.     move.w    #$20,-(sp)        ;    ... it's a plane ...
  1130.     trap    #1            ;      ... no, its:
  1131.     addq    #6,sp            ; SOOUPERUSER!
  1132.     move.l    d0,savssp        ; "Faster than a prefetched opcode..."
  1133.  
  1134. nboot3:    move    #maxunits-1,d1
  1135.     moveq    #-1,d0            ; a bad pun
  1136.     lea    pun,a0
  1137. i_sasi2: move.b    d0,(a0)+
  1138.     dbra    d1,i_sasi2
  1139.  
  1140.     move    #2,clun            ; current logical unit number
  1141.     move.l    #4,cdbit        ; current drive bit
  1142.     move    #0,cpun            ; current physical unit number
  1143.     move    #0,installed        ; none installed yet
  1144.     move    #0,puns            ; no physical units found
  1145.  
  1146. i_sasi3:
  1147.     move.w    cpun,-(sp)        ; pread(sectno, cnt, buf, physunit)
  1148.     move.l    #pbuf,-(sp)
  1149.     move.w    #1,-(sp)        ; 1 sector
  1150.     move.l    #0,-(sp)        ; sectno = 0
  1151.     bsr    pread            ; try to read root sector
  1152.     adda    #12,sp
  1153.  
  1154.     tst.w    d0
  1155.     bne    i_sasi4            ; no controller/disk of that ACSI unit
  1156.  
  1157.     addq    #1,puns            ; found a physical unit
  1158.  
  1159.     bsr    ppu
  1160.  
  1161.     addq    #1,cpun
  1162.     cmpi    #8,cpun
  1163.     bne    i_sasi3
  1164.  
  1165. i_sasi4: tst    puns            ; any drives found?
  1166.     beq    isase            ; nope, so just terminate
  1167.  
  1168.     clr.l    a5            ; zeropage ptr
  1169.     move.l    hdv_bpb(a5),o_bpb    ; save old vectors
  1170.     move.l    hdv_rw(a5),o_rw
  1171.     move.l    hdv_mediach(a5),o_mediach
  1172.  
  1173.     move.l    #hbpb,hdv_bpb(a5)    ; install our new ones
  1174.     move.l    #hrw,hdv_rw(a5)
  1175.     move.l    #hmediach,hdv_mediach(a5)
  1176.     move.l    #_puns,pun_ptr(a5)
  1177.  
  1178.     bra    isasi5        ; must get back into resident part
  1179.  
  1180. isase:    tst.w    bootloaded    ; if bootloaded, free block and punt
  1181.     bne    isaseb
  1182.     move.l    savssp,-(sp)    ; become a mild mannered user process
  1183.     move.w    #$20,-(sp)    ; Super(savssp)
  1184.     trap    #1
  1185.     addq    #6,sp
  1186.  
  1187.     move.w    #-1,-(sp)    ; exit code
  1188.     move.w    #$4C,-(sp)    ; terminate
  1189.     trap    #1        ; should never come back...
  1190.     illegal
  1191.  
  1192. ;
  1193. ;  Couldn't install driver, return to boot code
  1194. ;
  1195. isaseb:    move.l    baseaddr,-(sp)    ; Mfree(baseaddr)
  1196.     move.w    #$49,-(sp)
  1197.     trap    #1
  1198.     addq.l    #6,sp
  1199.     move.b    #$100-$20,d7    ; return to TOS ROMs
  1200.     rts
  1201.  
  1202.  
  1203.     .subttl    'Partition Support'
  1204. ;----------------
  1205. ;
  1206. ;  pread(sectno, cnt, buf, physunit)
  1207. ;    LONG sectno;
  1208. ;    BYTE *buf; (word aligned)
  1209. ;    WORD cnt,physunit;
  1210. ;
  1211. ;    Passed:    dev.w        $a(a0)    $e(sp)
  1212. ;        &buf.l        $6(a0)    $a(sp)
  1213. ;        cnt.w        $4(a0)    $8(sp)
  1214. ;        sectno.l    $0(a0)    $4(sp)
  1215. ;
  1216. ;    Returns:    -1 if we could not read it (may not exist)
  1217. ;
  1218. _pread:
  1219. pread:    move    _retries,retrycnt
  1220. pread1:    lea    4(sp),a0        ; frame pointer
  1221.     move.w    $a(a0),-(sp)        ; push physical unit number
  1222.     move.l    $6(a0),-(sp)        ; buffer address
  1223.     move.w    $4(a0),-(sp)        ; number to read
  1224.     move.l    (a0),-(sp)        ; sector number
  1225.     bsr    _hread
  1226.     adda    #12,sp
  1227.     tst    d0
  1228.     beq    pread9            ; no problems
  1229.     bmi    pread8            ; timeout, does not exist
  1230.     subq    #1,retrycnt        ; read error, try try again
  1231.     bpl    pread1
  1232. pread8:    moveq    #-1,d0
  1233.     rts
  1234.  
  1235. pread9:    move    #$8000,d0        ; delay for completion byte
  1236. preada:    subq    #1,d0
  1237.     bne    preada
  1238.     clr.l    d0            ; flag no errors
  1239.     rts
  1240.  
  1241.  
  1242.     .eject
  1243. ;----------------
  1244. ;
  1245. ;  Partition physical unit
  1246. ;
  1247. ppu:    move    #0,npart        ; number of partitions we have found
  1248.     movea.l    #pbuf+hd_siz,a0
  1249.     tst.l    (a0)+
  1250.     beq    ppu3            ; if 0, must not be valid
  1251.  
  1252.     moveq    #4-1,d1            ; maximum number of partitions/unit
  1253. ppu1:    movem.l    d1/a0,-(sp)
  1254.     tst.b    (a0)+            ; check the valid partition flag
  1255.     beq    ppu2            ; if 0, not a valid parition
  1256.  
  1257.     addq    #1,npart        ; number of partitions this unit
  1258.  
  1259.     cmpi.b    #'G',(a0)+        ; must find GEM as type
  1260.     bne    ppu2
  1261.     cmpi.b    #'E',(a0)+
  1262.     bne    ppu2
  1263.     cmpi.b    #'M',(a0)+
  1264.     bne    ppu2
  1265.  
  1266.     tst.l    4(a0)            ; is the size 0?
  1267.     beq    ppu2            ; then not a valid partition
  1268.  
  1269.     move.l    (a0),-(sp)        ; save start sector
  1270.  
  1271.     bsr    nxtdrv
  1272.  
  1273.     move.l    (sp)+,d1        ; recall start sector
  1274.  
  1275.     tst    d0            ; valid unit?
  1276.     bmi    ppu2
  1277.  
  1278.     movem.l    d1/a0-a1,-(sp)
  1279.  
  1280.     move.l    d1,-(sp)        ; getbpb(partition_start)
  1281.     bsr    getbpb            ; build bpb and put it in place
  1282.     addq    #4,sp
  1283.  
  1284.     movem.l    (sp)+,d1/a0-a1
  1285.  
  1286.     tst    d0
  1287.     bne    ppu2
  1288.  
  1289.     move.w    cpun,d0
  1290.     move.b    d0,(a0)
  1291.  
  1292.     move.l    d1,(a1)            ; start of partition
  1293.  
  1294.     addq    #1,clun
  1295.     addq    #1,installed        ; actually installed a hard disk
  1296.  
  1297. ppu2:    movem.l    (sp)+,d1/a0
  1298.     adda    #12,a0
  1299.     dbra    d1,ppu1
  1300.  
  1301.     tst    npart            ; did we find any?
  1302.     bne    ppu9
  1303.  
  1304. ppu3:    bsr    nxtdrv            ; no valid partitions found, assume
  1305.     move    cpun,d0            ;  whole thing is one big GEM disk
  1306.     move.b    d0,(a0)
  1307.     move.w    #0,(a1)            ; starts at 0
  1308.     lea    thebpb,a1
  1309.     move    #BPBLEN-1,d0
  1310. ppu4:    move.b    (a1)+,(a2)+
  1311.     dbra    d0,ppu4
  1312.  
  1313.     addq    #1,clun
  1314.     addq    #1,installed
  1315.  
  1316. ppu9:    rts
  1317.  
  1318.  
  1319.     .eject
  1320. ;+
  1321. ; nxtdrv    (of clun, cdbit)
  1322. ;    returns d0 = clun, or negative if error
  1323. ;        a0 -> pun(clun)
  1324. ;        a1 -> start(clun)
  1325. ;        a2 -> bpbs(clun)
  1326. ;-
  1327.  
  1328. nxtdrv:    cmpi    #maxunits,clun        ; have we already hit maximum?
  1329.     bge    nxtd9            ; yes, so signal error
  1330.  
  1331.     move.l    cdbit,d1        ; get the next bit to turn on
  1332.     move.l    _drvbits,d0        ; tell TOS we have the drive
  1333.     or.l    d1,d0
  1334.     move.l    d0,_drvbits
  1335.  
  1336.     asl.l    #1,d1
  1337.     move.l    d1,cdbit
  1338.     move    clun,d0
  1339.     lea    pun,a0
  1340.     adda    d0,a0
  1341.     lea    start,a1
  1342.     move    d0,d1
  1343.     asl    #2,d1            ; *4 for index into table of longs
  1344.     adda    d1,a1
  1345.     lea    bpbs,a2
  1346.     move    d0,d1
  1347.     mulu    #BPBLEN,d1
  1348.     adda    d1,a2
  1349.     rts
  1350.  
  1351. nxtd9:    moveq    #-1,d0
  1352.     rts
  1353.  
  1354.     .eject
  1355. ;+
  1356. ; getbpb(sectorno)
  1357. ; LONG sectorno;
  1358. ;-
  1359.  
  1360. getbpb:    move.l    a2,-(sp)
  1361.  
  1362.     move.w    cpun,-(sp)        ; try to read this partition's
  1363.     move.l    #lbuf,-(sp)        ; boot sector
  1364.     move.w    #1,-(sp)        ; number of sectors
  1365.     move.l    16(sp),-(sp)        ; sectorno
  1366.     bsr    pread            ; pread(sectno, cnt, buf, physunit)
  1367.     adda    #12,sp
  1368.  
  1369.     movea.l    (sp)+,a2
  1370.  
  1371.     tst    d0            ; any trouble reading?
  1372.     bmi    getb9            ; bummer
  1373.  
  1374.     lea    lbuf,a3            ; pointer to boot sector
  1375.  
  1376.     move    #$0b,d0
  1377.     bsr    getlhw
  1378.     move    d0,(a2)+        ; =byt/sec
  1379.     move    d0,d1
  1380.  
  1381.     clr.w    d0
  1382.     move.b    $d(a3),d0
  1383.     move    d0,(a2)+        ; =sec/cluster
  1384.  
  1385.     mulu    d1,d0
  1386.     move    d0,(a2)+        ; =byt/cluster
  1387.  
  1388.     move    #$11,d0
  1389.     bsr    getlhw            ; number of directory entries
  1390.     mulu    #32,d0            ; size of each entry
  1391.     divu    d1,d0            ; number of sectors required
  1392.     move.l    d0,d1
  1393.     swap    d1
  1394.     tst    d1
  1395.     beq    getb1
  1396.     addq    #1,d0            ; round up
  1397. getb1:    move    d0,(a2)+        ; =rdlen
  1398.     move    d0,d2
  1399.  
  1400.     move    #$16,d0
  1401.     bsr    getlhw
  1402.     move    d0,(a2)+        ; =FATsize
  1403.     move    d0,d1
  1404.  
  1405.     move    #$e,d0
  1406.     bsr    getlhw            ; number of reserved sectors
  1407.     add    d1,d0
  1408.     move    d0,(a2)+        ; =2nd FAT start
  1409.  
  1410.     add    d1,d0            ; plus size of second fat
  1411.     add    d2,d0            ; plus rdlen
  1412.     move    d0,(a2)+        ; = data start
  1413.     move    d0,d2            ; save start of data
  1414.  
  1415.     move    #$13,d0
  1416.     bsr    getlhw            ; number of sectors on media
  1417.     sub    d2,d0            ; subtract number used by FATs,dir,boot
  1418.     clr.l    d1
  1419.     move    d0,d1
  1420.     clr    d0
  1421.     move.b    $d(a3),d0        ; number of sectors/cluster
  1422.     divu    d0,d1            ; rounding down
  1423.     move    d1,(a2)+        ; =number of clusters
  1424.     move    #1,(a2)            ; =flags, 16 bit fats
  1425.     clr.l    d0            ; no errors
  1426. getb9:    rts
  1427.  
  1428.  
  1429. ;+
  1430. ; WORD getlhw(d0=offset)
  1431. ; returns word (low,high) from 0(D0,A3)
  1432. ;-
  1433.  
  1434. getlhw:    move    d1,-(sp)        ; preserve d1
  1435.     move.b    1(a3,d0.w),d1
  1436.     lsl.w    #8,d1
  1437.     move.b    0(a3,d0.w),d1
  1438.     move    d1,d0
  1439.     move    (sp)+,d1
  1440.     rts
  1441.  
  1442.     .subttl    'Format Hard Disk'
  1443.     .if format
  1444.  
  1445.  
  1446. ;----------------
  1447. ;
  1448. ;  Parameter Block
  1449. ;
  1450. acfmt:    dc.b    4    ; format command + devno (upper 3 bits)
  1451.     dc.b    0    ; (unused)
  1452.     dc.b    0    ; (unused) data pattern
  1453. ac_in:    dc.b    0,0    ; interleave factor MSB, LSB
  1454.     dc.b    0    ; reserved
  1455.     .EVEN
  1456.  
  1457.  
  1458. ;----------------
  1459. ;
  1460. ;  _doformat - format hard disk
  1461. ;
  1462. ;    Synopsis:    LONG _doformat(dev, interlv)
  1463. ;        WORD dev;            4(sp).W
  1464. ;        WORD interlv;            6(sp).W
  1465. ;
  1466.  
  1467. _doformat:
  1468.     move.w    4(sp),d0        ; set dev#
  1469.     lsl.b    #5,d0            ; up 5 bits, fill in 0s
  1470.     or.b    #4,d0            ; OR-in with FORMAT command
  1471.     move.b    d0,acfmt        ; stuff into command frame
  1472.     move.b    6(sp),ac_in        ; set interleave
  1473.     move.b    7(sp),ac_in+1
  1474.  
  1475.     lea    acfmt(pc),a0        ; pick up pointer to the command block
  1476.     clr.w    d0
  1477.     st    flock            ; lock FIFO
  1478.     move.w    #$88,wdl
  1479.     move.b    (a0)+,d0        ; get the command byte
  1480.     swap    d0
  1481.     move.w    #$8a,d0
  1482.     move.l    d0,wdc            ; byte wdc 8a wdl
  1483.  
  1484.     moveq    #(5-1),d1        ; write remaining 5 bytes of command
  1485. fmt1:    bsr    _qdone
  1486.     bmi    _hto
  1487.     move.b    (a0)+,d0        ; next byte of command
  1488.     swap    d0
  1489.     move.w    #$8a,d0
  1490.     move.l    d0,wdcwdl
  1491.     dbra    d1,fmt1
  1492.  
  1493. fmt2:    btst    #5,gpip            ; wait (forever) for completion
  1494.     bne    fmt2
  1495.     move.w    wdc,d0            ; get the status
  1496.     andi.w    #$00FF,d0        ; only low byte is significant
  1497.     bra    _hdone            ; cleanup after IRQ
  1498.  
  1499.     .subttl    'Set Format Parameters'
  1500.  
  1501. ;----------------
  1502. ;
  1503. ;  _mode_set - set hard disk format parameters
  1504. ;
  1505. ;    Synopsis:    LONG _mode_set(dev, parms)
  1506. ;        WORD dev;            4(sp).W
  1507. ;        char *parms;            6(sp).L
  1508. ;
  1509. _mode_set:
  1510.     st    flock            ; lock FIFO
  1511.     move.l    6(sp),-(sp)        ; -> parameter block address
  1512.     bsr    _setdma            ; set DMA there
  1513.     addq    #4,sp
  1514.  
  1515. ;---
  1516. ;   write command and dev#
  1517. ;
  1518.     move.w    #$88,wdl
  1519.     move.w    4(sp),d0        ; d0 = (dev << 5) << 16
  1520.     lsl.b    #5,d0
  1521.     swap    d0            ; in upper word
  1522.     or.l    #$0015008a,d0        ; write dev# + ModeSelect + FIFO bits
  1523.     move.l    d0,wdcwdl        ; mdsel+dev wdc 8a wdl (byte 0)
  1524.     bsr    _qdone
  1525.     bmi    wdx
  1526.  
  1527.     move.l    #$0000008a,wdcwdl    ; byte 1
  1528.     bsr    _qdone
  1529.     bmi    wdx
  1530.  
  1531.     move.l    #$0000008a,wdcwdl    ; byte 2
  1532.     bsr    _qdone
  1533.     bmi    wdx
  1534.  
  1535.     move.l    #$0000008a,wdcwdl    ; byte 3
  1536.     bsr    _qdone
  1537.     bmi    wdx
  1538.  
  1539.     move.l    #$0016008a,wdcwdl    ; 22 bytes of parameters (byte 4)
  1540.     bsr    _qdone
  1541.     bmi    wdx
  1542.  
  1543.     move.w    #$90,wdl        ; reset the DMA chip
  1544.     nop
  1545.     move.w    #$190,wdl
  1546.     nop
  1547.     move.w    #$01,wdc        ; 1 sector of DMA (actually less)
  1548.     nop
  1549.     move.w    #$18a,wdl
  1550.     nop
  1551.     move.l    #$00000100,wdcwdl    ; byte 5 (control byte)
  1552.     move.w    #$18a,d0        ; wdl value
  1553.     bsr    _endcmd            ; wait for command completion
  1554. wdx:    bra    _hdone
  1555.  
  1556.   .endif    ; format
  1557.  
  1558.     .eject
  1559.   .if sahdxc
  1560. ;+
  1561. ; LONG _dosahdxc( dev, addr ) BYTE *addr;
  1562. ;    do a simple (no DMA) ahdx command
  1563. ;-
  1564. _dosahdxc: movea.l 6(sp),a0        ; pick up pointer to the command block
  1565.     clr.w    d0
  1566.     st    flock            ; lock FIFO
  1567.     move.w    #$88,wdl
  1568.     move    4(sp),d0        ; get the unit number
  1569.     lsl    #5,d0            ; shift it into place
  1570.     or.b    (a0)+,d0        ; or in the command byte
  1571.     swap    d0
  1572.     move.w    #$8a,d0
  1573.     move.l    d0,wdcwdl        ; send it to the controller
  1574.  
  1575.     moveq    #(5-1),d1        ; write remaining 5 bytes of command
  1576. dosac1:    bsr    _qdone
  1577.     bmi    _hto
  1578.     move.b    (a0)+,d0        ; next byte of command
  1579.     swap    d0
  1580.     move.w    #$8a,d0
  1581.     move.l    d0,wdcwdl
  1582.     dbra    d1,dosac1
  1583.  
  1584.     bsr    _fdone            ; wait for the command to complete
  1585.     bmi    _hto
  1586.  
  1587.     move.w    wdc,d0            ; get the status
  1588.     andi.w    #$00FF,d0        ; only low byte is significant
  1589.  
  1590.     bra    _hdone            ; cleanup after IRQ
  1591.  
  1592.   .endif    ; sahdxc
  1593.  
  1594.  
  1595.     .subttl    'Prototype BPBs'
  1596.   .if s10mb
  1597. ;+
  1598. ; BPB for 10MB drive
  1599. ;-
  1600. thebpb:    dc.w    512            ; #bytes/sector
  1601.     dc.w    2            ; #sectors/cluster
  1602.     dc.w    1024            ; #bytes/cluster
  1603.     dc.w    16            ; rdlen (256 root files) (in sectors)
  1604.     dc.w    41            ; FATsiz (10300 FAT entries) (sectors)
  1605.     dc.w    42            ; 2nd FAT start
  1606.     dc.w    99            ; data start (in sectors)
  1607.     dc.w    10300            ; #clusters (approximate here)
  1608.     dc.w    1            ; flags (16-bit FATs)
  1609.   .endif
  1610.  
  1611.   .if s20mb
  1612. ;+
  1613. ; BPB for 20MB drive
  1614. ;-
  1615. thebpb:    dc.w    512            ; #bytes/sector
  1616.     dc.w    2            ; #sectors/cluster
  1617.     dc.w    1024            ; #bytes/cluster
  1618.     dc.w    32            ; rdlen (512 root files) (in sectors)
  1619.     dc.w    81            ; FATsiz (20736 FAT entries) (sectors)
  1620.     dc.w    82            ; 2nd FAT start
  1621.     dc.w    195            ; data start (in sectors)
  1622.     dc.w    20710            ; #clusters (approximate here)
  1623.     dc.w    1            ; flags (16-bit FATs)
  1624.   .endif
  1625.  
  1626.   .if sahdxc
  1627.  
  1628. actur:    dc.b    0,0,0,0,0,0        ; atari command: test unit ready
  1629.  
  1630.   .endif    ; sahdxc
  1631.  
  1632.  
  1633.     .even
  1634.  
  1635.     bss
  1636. savssp:    ds.l    1            ; (saved SSP)
  1637. clun:    ds.w    1
  1638. cpun:    ds.w    1
  1639. cdbit:    ds.l    1
  1640. npart:    ds.w    1            ; number of partitions found this pun
  1641. installed: ds.w    1            ; number hard disk partitions installed
  1642.  
  1643. hd_siz    equ    $1c2            ; offset into pbuf for partition info
  1644. pbuf:    ds.b    512
  1645. lbuf:    ds.b    512
  1646.  
  1647.     end
  1648.